home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 8 / QRZ Ham Radio Callsign Database - Volume 8.iso / mac / files / misc / hamrtty.arc / TTYLNY.ASM < prev    next >
Assembly Source File  |  1980-01-01  |  42KB  |  1,126 lines

  1.         PAGE    ,132
  2.         TITLE   TTY - Radio Teletype Communications Program
  3. ;
  4. ;       TTY is a program which allows the IBM Personal
  5. ;       Computer to be used as a radio teletype terminal.
  6. ;
  7. ;       This program runs under PC-DOS.
  8. ;       The terminal unit must be connected to COM1.
  9. ;       The terminal unit must activate the DATA SET READY
  10. ;         status line to the COM1 port.
  11. ;
  12. ;       See CQ magazine, November 1983, for an explanation of
  13. ;       this program and how it works on the PC.
  14. ;
  15. ; Author: Jack Botner, VE3LNY
  16. ;         BOTNER at TOROLAB
  17. ; Date:   November 1983
  18. ; Made available to IBMARC by VE3LNY.
  19. ;
  20. ; Operation:
  21. ;
  22. ;       Type 'TTY' from DOS. Select the rtty code and baud rate.
  23. ;       The program then enters receive mode. To transmit, press
  24. ;       F5. To send your CWid at the end of a transmission, press
  25. ;       F6. To return to receive, press F10. To select another
  26. ;       rtty code/baud rate, or end the program, press F10 again.
  27. ;       In receive using Murray code, if noise causes a false
  28. ;       shift, use the F2 key to correct the shift state.
  29. ;
  30. ;       Note that receive errors are common on RTTY, due to noise
  31. ;       and interference on the signals. This program detects some
  32. ;       of these errors as "framing" errors. The symbol corresponding
  33. ;       to ascii code 15 (decimal) is displayed when one or more
  34. ;       receive errors are detected. This symbol appears like a
  35. ;       double asterisk and tells you that there are receive errors.
  36. ;
  37. ;*****************************************************************
  38. ; Use of this program is subject to the following conditions:
  39. ; 1. That it be distributed to and used by licenced amateur radio
  40. ;    operators only;
  41. ; 2. That it be used for amateur radio purposes only;
  42. ; 3. Under no circumstances can this program be sold or otherwise
  43. ;    used commercially or for profit;
  44. ; 4. That the origin and purpose of this program not be removed
  45. ;    from this source code file.
  46. ;*****************************************************************
  47. ;
  48. ;  Macro Definitions
  49. DISPLAY MACRO   TEXT
  50.         MOV     DX,OFFSET TEXT
  51.         MOV     AH,9            ;Print String DOS function
  52.         INT     21H             ;call DOS
  53.         ENDM
  54. ;
  55. LOCATE  MACRO
  56.         MOV     AH,3            ;Read cursor posn BIOS function
  57.         XOR     BH,BH           ;Page 0
  58.         INT     10H             ;call BIOS
  59.         ENDM
  60. ;
  61. SETCRS  MACRO
  62.         MOV     AH,2            ;set cursor position BIOS function
  63.         XOR     BH,BH           ;page 0
  64.         INT     10H             ;call BIOS
  65.         ENDM
  66. ;
  67. SCROLL  MACRO
  68.         MOV     AH,6            ;Scroll up BIOS function
  69.         XOR     CX,CX           ;begin row,col = 1,1
  70.         MOV     DH,21           ;end row = 22
  71.         MOV     DL,79           ;end col = 80
  72.         MOV     BH,00000111B    ;attribute byte
  73.         INT     10H             ;call BIOS
  74.         ENDM
  75. ;
  76. ;  Equates
  77. CR      EQU     0DH
  78. LF      EQU     0AH
  79. BEL     EQU     0EH             ;Bell symbol (display)
  80. ERR     EQU     0FH             ;Error symbol for display
  81. ;
  82. STACK   SEGMENT PARA STACK 'STACK'
  83.         DB      64 DUP ('STACK   ')
  84. STACK   ENDS
  85. ;
  86.         SUBTTL  TTY Data and Workarea Definitions
  87. ;
  88. DATA    SEGMENT PARA PUBLIC 'DATA'
  89. CWID    DB      'DE URCALL$'    ;Your call here for CWid
  90. ;
  91. ;  Communications Parameters Tables for 8250 COM1.
  92. ;  Table entries correspond to fkey descriptions
  93. ;  for Fkeys:     F1  F2  F3
  94. DLABM   DB      00AH,06H,04H    ;Divisor Latch most significant byte
  95. DLABL   DB      000H,14H,17H    ;Divisor latch least significant byte
  96. LCR     DB      004H,04H,3EH    ;Line control reg. (bits, parity, etc.)
  97. RCODE   DB      001H,01H,02H    ;1=murray (baudot), 2=ascii code
  98. REQUEST DB      0               ;Which Fkey was selected
  99. ;
  100. ;  Main selection panel
  101. PANEL1  DB      'Teletype Terminal Program',CR,LF,CR,LF,CR,LF
  102.         DB      'F1: Murray 45 baud, 5 data bits, 2 stop bits, parity N'
  103.         DB      CR,LF,CR,LF
  104.         DB      'F2: Murray 74 baud, 5 data bits, 2 stop bits, parity N'
  105.         DB      CR,LF,CR,LF
  106.         DB      'F3: Ascii 110 baud, 7 data bits, 2 stop bits, parity S'
  107.         DB      CR,LF,CR,LF
  108.         DB      'F10: END Program$'
  109. ;
  110. LIN25   DB      'F2=SHIFT  F5=XMIT  F6=CWID  F10=END$'
  111. ERR1    DB      CR,LF,'No communications adapter address in system.'
  112.         DB      CR,LF,'$'
  113. ERR2    DB      CR,LF,'Time-out error on communications adapter.'
  114.         DB      ' Check your modem/TU',CR,LF,'$'
  115. ERR3    DB      CR,LF,'Your display must be configured for 80 column'
  116.         DB      ' width.',CR,LF,'$'
  117. ERR4    DB      'and press any key to retry (Esc key to end).'
  118.         DB      CR,LF,'$'
  119. ;
  120. RMSG    DB      'Receiving...$'
  121. TMSG    DB      'Transmitting...$'
  122. ;
  123. ;   Tables for converting Murray to Ascii & back
  124. LTRTAB  DB      0,'E',LF,'A SIU',CR,'DRJNFCKTZLWHYPQOBG MXV '
  125. FIGTAB  DB      0,'3',LF,'- ',BEL,'87',CR,'$4',27H,',!:(5',22H
  126.         DB      ')2#6019?& ./; '
  127. ;
  128. ; bit 0: 0 = char defined, 1 = char not defined
  129. ; bit 1: 0 = LTRS, 1 = FIGS
  130. ; bit 2: 1 = same code for either shift
  131. ; bits 3-7: Murray code for character
  132. ;                           LF
  133. MURRAY  DB      10 DUP(80H),22H,80H,80H
  134. ;               CR              SP   !   "   #   $   %   &
  135.         DB      28H,18 DUP(80H),24H,4DH,51H,54H,49H,80H,5AH
  136. ;                '   (   )   *   +   ,   -   .   /   0   1   2   3   4
  137.         DB      4BH,4FH,52H,80H,80H,4CH,43H,5CH,5DH,56H,57H,53H,41H,4AH
  138. ;                5   6   7   8   9   :   ;   <   =   >   ?   @   A   B
  139.         DB      50H,55H,47H,46H,58H,4EH,5EH,80H,80H,80H,59H,80H,03H,19H
  140. ;                C   D   E   F   G   H   I   J   K   L   M   N   O   P
  141.         DB      0EH,09H,01H,0DH,1AH,14H,06H,0BH,0FH,12H,1CH,0CH,18H,16H
  142. ;                Q   R   S   T   U   V   W   X   Y   Z     ╒\σ^_    '
  143.         DB      17H,0AH,05H,10H,07H,1EH,13H,1DH,15H,11H,5 DUP(80H),4BH
  144. ;                a   b   c   d   e   f   g   h   i   j   k   l   m   n
  145.         DB      03H,19H,0EH,09H,01H,0DH,1AH,14H,06H,0BH,0FH,12H,1CH,0CH
  146. ;                o   p   q   r   s   t   u   v   w   x   y   z     {]}~
  147.         DB      18H,16H,17H,0AH,05H,10H,07H,1EH,13H,1DH,15H,11H,5 DUP(80H)
  148. ;
  149. LCRAD   DW      ?               ;8250 LCR address
  150. ;                                CW Speed Factor - larger number
  151. SPEED   DW      16000           ; means slower CW speed
  152. CWIDPTR DW      ?
  153. ;
  154. ;  Table for generating CWid.
  155. ;  Each hex byte 'ab' in the table represents the following:
  156. ;    1. Turn the Break bit on in the comm adapter
  157. ;    2. Wait 'a' units of time
  158. ;    3. Turn the Break bit off in the comm adapter
  159. ;    4. Wait 'b' units of time.
  160. ;  When 'b' equals 2, the character is complete.
  161. TABLE   DB      'A',11H,32H,00H,00H,00H,00H
  162.         DB      'B',31H,11H,11H,12H,00H,00H
  163.         DB      'C',31H,11H,31H,12H,00H,00H
  164.         DB      'D',31H,11H,12H,00H,00H,00H
  165.         DB      'E',12H,00H,00H,00H,00H,00H
  166.         DB      'F',11H,11H,31H,12H,00H,00H
  167.         DB      'G',31H,31H,12H,00H,00H,00H
  168.         DB      'H',11H,11H,11H,12H,00H,00H
  169.         DB      'I',11H,12H,00H,00H,00H,00H
  170.         DB      'J',11H,31H,31H,32H,00H,00H
  171.         DB      'K',31H,11H,32H,00H,00H,00H
  172.         DB      'L',11H,31H,11H,12H,00H,00H
  173.         DB      'M',31H,32H,00H,00H,00H,00H
  174.         DB      'N',31H,12H,00H,00H,00H,00H
  175.         DB      'O',31H,31H,32H,00H,00H,00H
  176.         DB      'P',11H,31H,31H,12H,00H,00H
  177.         DB      'Q',31H,31H,11H,32H,00H,00H
  178.         DB      'R',11H,31H,12H,00H,00H,00H
  179.         DB      'S',11H,11H,12H,00H,00H,00H
  180.         DB      'T',32H,00H,00H,00H,00H,00H
  181.         DB      'U',11H,11H,32H,00H,00H,00H
  182.         DB      'V',11H,11H,11H,32H,00H,00H
  183.         DB      'W',11H,31H,32H,00H,00H,00H
  184.         DB      'X',31H,11H,11H,32H,00H,00H
  185.         DB      'Y',31H,11H,31H,32H,00H,00H
  186.         DB      'Z',31H,31H,11H,12H,00H,00H
  187.         DB      '1',11H,31H,31H,31H,32H,00H
  188.         DB      '2',11H,11H,31H,31H,32H,00H
  189.         DB      '3',11H,11H,11H,31H,32H,00H
  190.         DB      '4',11H,11H,11H,11H,32H,00H
  191.         DB      '5',11H,11H,11H,11H,12H,00H
  192.         DB      '6',31H,11H,11H,11H,12H,00H
  193.         DB      '7',31H,31H,11H,11H,12H,00H
  194.         DB      '8',31H,31H,31H,11H,12H,00H
  195.         DB      '9',31H,31H,31H,31H,12H,00H
  196.         DB      '0',31H,31H,31H,31H,32H,00H
  197.         DB      '.',11H,31H,11H,31H,11H,32H
  198.         DB      ',',31H,31H,11H,11H,31H,32H
  199.         DB      '-',31H,11H,11H,11H,32H,00H
  200.         DB      '?',11H,11H,31H,31H,11H,12H
  201.         DB      '/',31H,11H,11H,31H,12H,00H
  202.         DB      0FFH            ;Mark end of table
  203. ;
  204. SW1     DB      0               ;Program switches
  205. SHON    EQU     10000000B       ;Shift state = FIGS
  206. TRON    EQU     01000000B       ;In transmit state
  207. AERRON  EQU     00100000B       ;Ascii error flag
  208. OVRUN   EQU     00010000B       ;Overrun error occurred bit
  209. FERON   EQU     00001000B       ;Last char had framing error bit
  210. ASCII   EQU     00000001B       ;0=Murray, 1=ASCII
  211. ;
  212. SW2     DB      0
  213. CRON    EQU     10000000B       ;Last char was CR
  214. LFON    EQU     01000000B       ;Last char was LF
  215. DATA    ENDS
  216. ;
  217.         SUBTTL  TTY Code Segment: Mainline
  218. ;
  219. CODE    SEGMENT PARA PUBLIC 'CODE'
  220.         ASSUME  CS:CODE,DS:DATA,SS:STACK
  221. TTY     PROC    FAR
  222.         PUSH    DS              ;Establish conditions for
  223.         XOR     AX,AX           ;  FAR return to DOS at
  224.         PUSH    AX              ;  end of program.
  225.         MOV     AX,DATA
  226.         MOV     DS,AX
  227.         MOV     ES,AX           ;ES=DS
  228.         JMP     START
  229. ;
  230. ;  COM1 receive interrupt routine workarea
  231. COMADDR DW      ?               ;8250 Async Adapter Address
  232. ADBUF   DB      32 DUP (?)      ;Receive buffer: data
  233. ERBUF   DB      32 DUP (?)      ;Receive buffer: status codes
  234. INPTR   DB      0               ;Insert byte count
  235. OUTPTR  DB      0               ;Extract byte count
  236. ADLEN   DB      32              ;Buffer length
  237. ADCNT   DB      0               ;Byte count
  238. ;
  239. START:  CLD
  240. ;  Make sure display configured for 80 columns
  241.         MOV     AH,15           ;Current video state BIOS function
  242.         INT     10H             ;call BIOS
  243.         CMP     AH,80           ;Width = 80?
  244.         JE      IA100
  245.         DISPLAY ERR3            ;Invalid display config.
  246.         JMP     PGMEXIT
  247. ;
  248. ;  The ACA address is taken from the first COM adapter addresses
  249. ;  in the ROM BIOS Data Area, located at segment address 40H.
  250. ;  The COM adapter address is extracted, and validated to make
  251. ;  sure the adapter is actually installed.
  252. IA100:  PUSH    ES
  253.         MOV     AX,40H
  254.         MOV     ES,AX                   ;ROM BIOS Data Area Segment
  255.         MOV     AX,WORD PTR ES:0        ;Get RS232 Base Address
  256.         POP     ES
  257.         CMP     AX,0
  258.         JNE     IA300
  259.         DISPLAY ERR1                    ;Invalid adapter specification
  260.         JMP     PGMEXIT
  261. ;
  262. IA300:  MOV     COMADDR,AX              ;Save RS232 Adapter Address
  263. ;
  264. ;  Initialize Communications Environment
  265. ;
  266. ;  Initialize Modem Control Register with DTR flag
  267.         MOV     DX,COMADDR      ;Reload adapter address
  268.         ADD     DX,4            ;Address Modem Control Register (3FC)
  269.         MOV     AL,00000001B    ;Turn DTR flag on, all others off
  270.         OUT     DX,AL           ;Write MCR register
  271. ;
  272. ;  Receive Modem Status Register from adapter
  273. IA500:  MOV     CX,22           ;Establish time-out count
  274.         MOV     DX,COMADDR      ;Reload adapter address
  275.         ADD     DX,6            ;Modem Status Register Address (3FE)
  276. ;
  277. IC100:  IN      AL,DX           ;Read Modem Status Register
  278.         TEST    AL,00100000B    ;Test Data Set Ready flag
  279.         JZ      IC300           ;DSR off - process error
  280.         JMP     IE100           ;DSR is on - continue
  281. ;
  282. IC300:  CALL    PAUSE           ;Retry CX times before giving up,
  283.         LOOP    IC100           ;  waiting PAUSE between retries
  284. ;
  285. ;  Process time-out error by giving user chance to try again
  286.         DISPLAY ERR2            ;State error
  287.         DISPLAY ERR4            ;State action
  288. ;                                Get response
  289.         MOV     AH,0CH          ;Clr kybd DOS req
  290.         MOV     AL,7            ;Then direct console input req
  291.         INT     21H             ;Call DOS
  292.         CMP     AL,0            ;Returned keystroke
  293.         JNE     ID100           ;Not extended ASCII
  294. ;                                Discard extended ascii code
  295.         MOV     AH,7            ;Direct console input req
  296.         INT     21H             ;Call DOS
  297.         JMP     IA500           ;Retry test for DSR
  298. ;
  299. ID100:  CMP     AL,27           ;ESCape key?
  300.         JE      ID300
  301.         JMP     IA500           ;Retry test for DSR
  302. ID300:  JMP     PGMEXIT         ;That's all, folks
  303. ;
  304. ; Establish 0C interrupt handling routine vector.
  305. IE100:  PUSH    DS
  306.         MOV     AH,25H          ;Set Interrupt Vector DOS function
  307.         MOV     AL,0CH          ;Interrupt type
  308.         MOV     CX,CS
  309.         MOV     DS,CX
  310.         MOV     DX,OFFSET INT0C ;ENTRY_0C
  311.         INT     21H             ;Call DOS
  312.         POP     DS
  313. ;
  314. ; Enable IRQ4 interrupt on 8259 interrupt controller
  315.         IN      AL,21H          ;Read IMR
  316.         AND     AL,11101111B    ;Turn off IRQ4 bit to enable interrupt
  317.         OUT     21H,AL          ;Write OCW1 (IMR)
  318. ;
  319. ;  Enter here to re-set communications parameters
  320. ;
  321. ;  Display TTY Initial Selection Panel
  322. INITIALIZE:
  323.         CALL    CLEAR           ;Clear the screen
  324.         MOV     DH,3            ;Row=4
  325.         XOR     DL,DL           ;Col=1
  326.         SETCRS                  ;Set cursor address to locate panel
  327. ;
  328.         DISPLAY PANEL1          ;Display selection panel
  329. ;
  330. IG100:  MOV     AH,8            ;Console input DOS req
  331.         INT     21H             ;Call DOS
  332.         CMP     AL,0            ;0=extended ascii code returned
  333.         JZ      IG300           ;Look for F1-F10
  334.         JMP     IG100           ;Pressed wrong key
  335. ;
  336. IG300:  MOV     AH,8            ;Console input DOS req
  337.         INT     21H             ;Call DOS
  338.         CMP     AL,59           ;F1
  339.         JE      IG500
  340.         CMP     AL,60           ;F2
  341.         JE      IG500
  342.         CMP     AL,61           ;F3
  343.         JE      IG500
  344.         CMP     AL,68           ;F10
  345.         JE      IG500
  346.         JMP     IG100
  347. ;
  348. IG500:  PUSH    AX
  349.         CALL    CLEAR           ;Clear the screen
  350.         XOR     DX,DX           ;Row 1, col 1
  351.         SETCRS                  ;Set cursor position
  352.         POP     AX
  353. ;
  354.         CMP     AL,68           ;F10?
  355.         JNE     IH100           ;No, select baud etc.
  356.         JMP     END_RUN         ;Run complete
  357. ;
  358. IH100:  SUB     AL,58           ;Make number relative to 0
  359.         MOV     REQUEST,AL      ;Save fkey number
  360.         SUB     BX,BX
  361.         MOV     BL,AL           ;Create index register for
  362.         DEC     BX              ;  table lookup
  363. ;
  364. ;  Write 1 into Divisor Latch Access Bit of Line Control Register
  365. ;  to allow access to Divisor Latches (Baud Rate Generator).
  366.         MOV     DX,COMADDR      ;Load adapter address
  367.         ADD     DX,3            ;Point to 8250 control register (3FB)
  368.         MOV     AL,80H
  369.         OUT     DX,AL           ;Set DLAB=1 (divisor latch access bit)
  370. ;
  371. ;  Write high-order byte of baud rate divisor to Divisor Latch
  372.         MOV     DX,COMADDR      ;Reload adapter address
  373.         INC     DX              ;Divisor Latch Most Sig. Bits (3F9)
  374.         MOV     AL,DLABM╒BXσ    ;Baud rate
  375.         OUT     DX,AL           ;Set baud rate Most Significant Bits
  376. ;
  377. ;  Write low-order byte of baud rate divisor to Divisor Latch
  378.         DEC     DX              ;Divisor Latch Least Sig. Bits (3F8)
  379.         MOV     AL,DLABL╒BXσ    ;Baud rate
  380.         OUT     DX,AL           ;Set Baud Rate Least Significant bits
  381. ;
  382. ;  Write Line Control Register to set Data Bits, Stop Bits, Parity,
  383. ;  and reset Divisor Latch Access Bit.
  384.         ADD     DX,3            ;Point to 8250 control reg. (3FB)
  385.         MOV     AL,LCR╒BXσ      ;Set Parity, Stop Bits, Word Lenth
  386.         OUT     DX,AL           ;Send Line Control Register Data
  387. ;
  388. ;  Write Interrupt Enable Register to enable 8250 interrupt.
  389. ;  Update Modem Control Register to enable interrupts
  390.         CALL    ENAINT          ;Enable interrupt for receive
  391. ;
  392. ;  Get code selection and build info lines
  393.         AND     SW1,0FFH-ASCII  ;Indicate Murray mode
  394.         MOV     AL,RCODE╒BXσ
  395.         CMP     AL,02
  396.         JNE     II100
  397.         OR      SW1,ASCII       ;Indicate ASCII mode
  398. ;
  399. ;  Display Fkey description line 25
  400. II100:  MOV     DH,24           ;Row 25
  401.         XOR     DL,DL           ;Col 1
  402.         SETCRS
  403.         DISPLAY LIN25
  404. ;
  405.         XOR     DX,DX           ;Row,col = 1,1
  406.         SETCRS
  407.         AND     SW1,0FFH-TRON-SHON-FERON
  408. ;
  409. ;  Scan keyboard for requests
  410. ;
  411. READ_KEYBD:
  412.         MOV     AH,0BH          ;Check Keyboard Status DOS code
  413.         INT     21H             ;Invoke DOS
  414.         CMP     AL,0            ;00=no character available
  415.         JNE     MA100
  416.         JMP     MF400
  417. ;
  418. MA100:  MOV     AH,8            ;Keyboard Input DOS code
  419.         INT     21H             ;Call DOS
  420.         CMP     AL,0            ;If AL=0 then char is extended ASCII code
  421.         JE      MB100           ;Go read second character
  422.         TEST    SW1,TRON        ;If receive mode, ignore character typed
  423.         JZ      MA500           ;  on keyboard and go poll adapter
  424.         JMP     SEND_ADAPTER
  425. MA500:  JMP     READ_ADAPTER
  426. ;
  427. ;  Process Extended ASCII code for function key requests.
  428. MB100:  MOV     AH,8            ;Keyboard Input again
  429.         INT     21H             ;Invoke DOS
  430.         CMP     AL,59
  431.         JB      MB500           ;Check for F1-F10 range
  432.         CMP     AL,68
  433.         JNA     MC300
  434. ;
  435. MB500:  TEST    SW1,TRON
  436.         JNZ     MC100           ;In receive mode, go scan ACA
  437.         JMP     READ_ADAPTER    ;  for received character.
  438. MC100:  JMP     READ_KEYBD
  439. ;
  440. MC300:  SUB     AL,58           ;F1-F10 selected.
  441. ;
  442.         CMP     AL,2            ;Check for F2 key (Toggle Shift)
  443.         JNE     MD300
  444.         TEST    SW1,ASCII       ;Does not apply to ASCII mode
  445.         JNZ     MC500
  446.         TEST    SW1,TRON        ;Allow in receive mode only
  447.         JZ      MC700
  448. MC500:  JMP     MF200           ;Sound alarm and continue
  449. ;
  450. MC700:  TEST    SW1,SHON        ;Process toggle shift
  451.         JZ      MD100
  452.         AND     SW1,0FFH-SHON   ;Turn the switch off
  453.         JMP     MF400
  454. MD100:  OR      SW1,SHON        ;Turn the switch on
  455.         JMP     MF400
  456. ;
  457. MD300:  CMP     AL,5            ;Check for F5 key (transmit request)
  458.         JNE     ME100
  459.         TEST    SW1,TRON        ;Allow in receive mode only
  460.         JZ      MD500
  461.         JMP     MF200           ;Sound alarm and continue
  462. ;
  463. MD500:  AND     SW1,0FFH-SHON   ;Reset to LTRS shift
  464.         OR      SW1,TRON        ;Set transmit mode
  465.         MOV     DX,OFFSET TMSG
  466.         CALL    DISPLAY_MESSAGE
  467.         CALL    DISINT          ;Disable 8250 adapter interrupts
  468. ;
  469.         CALL    RTSON           ;Turn on request-to-send signal
  470.         JMP     MF400
  471. ;
  472. ME100:  CMP     AL,6            ;Check for F6 key (send CW ID)
  473.         JNE     ME400
  474.         TEST    SW1,TRON
  475.         JNZ     ME300           ;Invalid request if in receive mode
  476.         JMP     MF200           ;Sound alarm and continue
  477. ;
  478. ME300:  CALL    CWID_RTN        ;send CW ID
  479.         JMP     MF400           ;OK
  480. ;
  481. ME400:  CMP     AL,10           ;Check for F10 key (END)
  482.         JE      ME500
  483.         JMP     MF200           ;Go sound alarm for bad Fkey
  484. ;
  485. ME500:  TEST    SW1,TRON        ;In transmit mode?
  486.         JNZ     ME700
  487.         JMP     MF100
  488. ;
  489. ME700:  AND     SW1,0FFH-TRON   ;Return to receive mode here
  490.         MOV     DX,OFFSET RMSG
  491.         CALL    DISPLAY_MESSAGE
  492. ;
  493.         CALL    ENAINT          ;Enable 8250 adapter interrupts
  494.         CALL    RTSOFF          ;Turn off request-to-send signal
  495.         JMP     MF400           ;Done with this request
  496. ;
  497. MF100:  CALL    DISINT          ;Disable 8250 adapter interrupts
  498.         CALL    RTSOFF          ;Turn off request-to-send signal
  499.         JMP     INITIALIZE      ;Return to main menu
  500. ;
  501. MF200   LABEL   NEAR
  502.         CALL    ALARM           ;Error or undefined key selected
  503. ;
  504. MF400:  TEST    SW1,TRON        ;End of F1-F10 processing
  505.         JNZ     MG100
  506.         JMP     READ_ADAPTER    ;In receive, continue scanning adapter
  507. MG100:  JMP     READ_KEYBD
  508. ;
  509. ;  Communicatiins Adapter SEND routine
  510. ;
  511. SEND_ADAPTER:                   ;Char from keyboard in AL
  512.         SUB     AH,AH
  513.         AND     AL,01111111B    ;Make sure high order bit is zero.
  514.         TEST    SW1,ASCII
  515.         JZ      MH100
  516.         MOV     DL,AL           ;ASCII: use character as entered
  517.         JMP     MH200
  518. ;
  519. MH100:  MOV     SI,AX           ;Murray: translate required
  520.         MOV     DL,MURRAY╒SIσ   ;Get Murray equivalent of ASCII
  521.         TEST    DL,10000000B    ;Test for invalid character
  522.         JZ      MH200
  523.         CALL    ALARM           ;Sound the alarm
  524.         JMP     MJ500           ;Bypass invalid character
  525. ;
  526. MH200:  PUSH    DX
  527.         MOV     DL,AL
  528.         CALL    DISPLAY_CHAR
  529.         POP     DX
  530. ;
  531.         TEST    SW1,ASCII       ;Bypass shift jazz for ASCII
  532.         JZ      MH400
  533.         JMP     MI200
  534. MH400:  TEST    DL,00100000B    ;Test shift irrelevant bit
  535.         JNZ     MI100
  536.         TEST    DL,01000000B    ;Test for shift
  537.         JZ      MH600
  538. ;                                Char to send is FIGS
  539.         TEST    SW1,SHON        ;What was sent last?
  540.         JNZ     MI100
  541.         MOV     AL,1BH          ;1B = FIGS
  542.         CALL    XMIT_CHAR
  543.         OR      SW1,SHON        ;Indicate in FIGS shift now
  544.         JMP     MI100
  545. ;
  546. MH600:  TEST    SW1,SHON        ;char to send is LTRS
  547.         JZ      MI100
  548.         MOV     AL,1FH          ;1F = LTRS
  549.         CALL    XMIT_CHAR
  550.         AND     SW1,0FFH-SHON   ;Indicate in LTRS shift now
  551. ;
  552. MI100:  AND     DL,00011111B
  553. ;                                Write char in DL to async adapter
  554. MI200:  MOV     AL,DL           ;Char to send
  555.         CALL    XMIT_CHAR
  556. ;
  557.         TEST    SW1,ASCII       ;Bypass shift jazz for ASCII
  558.         JNZ     MI500
  559.         CMP     DL,8            ;If a CR was sent (Murray 08H),
  560.         JE      MI400           ;  then a LF must also be sent
  561.         JMP     MJ500
  562. ;
  563. MI400:  MOV     DL,2            ;LF = Murray 02H
  564.         JMP     MJ300
  565. ;
  566. MI500:  CMP     DL,CR           ;If CR was sent (ASCII),
  567.         JE      MJ100           ;  then a LF must also be sent
  568.         JMP     MJ500
  569. ;
  570. MJ100:  MOV     DL,LF
  571. ;                                Write character in DL to ACA
  572. MJ300:  MOV     AL,DL           ;Char to send
  573.         CALL    XMIT_CHAR
  574.         MOV     DL,LF           ;Send to display too
  575.         CALL    DISPLAY_CHAR
  576. MJ500:  JMP     READ_KEYBD
  577. ;
  578. ;  Communications Adapter READ routine
  579. ;
  580. READ_ADAPTER:
  581.         CMP     ADCNT,0         ;See if anything is in the buffer
  582.         JA      MK100
  583.         JMP     READ_KEYBD      ;Buffer is empty - continue elsewhere
  584. ;
  585. ; The following statuses (of interest) are possible in ERBUF:
  586. ; Bit 3 = FRAMING ERROR         Bit 1 = OVERRUN ERROR
  587. MK100:  CLI                     ;no interrupts
  588.         SUB     BH,BH
  589.         MOV     BL,OUTPTR
  590.         MOV     AH,ERBUF╒BXσ    ;load status byte
  591.         MOV     AL,ADBUF╒BXσ    ;load data byte
  592.         INC     BL
  593.         CMP     BL,ADLEN        ;perform maintenance on buffer pointer
  594.         JB      MK300
  595.         SUB     BL,BL
  596. MK300:  MOV     OUTPTR,BL
  597.         DEC     ADCNT
  598.         STI                     ;Interrupts OK now
  599. ;
  600.         TEST    AH,00000010B    ;Overrun error?
  601.         JZ      MK500
  602.         OR      SW1,OVRUN       ;Indicate overrun error occurred
  603.         JMP     READ_ADAPTER    ;throw away byte
  604. ;
  605. MK500:  TEST    AH,00001000B    ;Framing error?
  606.         JZ      ML200
  607.         TEST    SW1,FERON       ;Was the last character in error too?
  608.         JZ      ML100
  609.         JMP     READ_ADAPTER    ;Yes, ignore this character (gibberish)
  610. ;
  611. ML100:  OR      SW1,FERON       ;No, turn on error indicator
  612.         MOV     DL,ERR          ;Indicate error occurred
  613.         JMP     MM700
  614. ;
  615. ML200:  AND     SW1,0FFH-FERON  ;RESET error switch
  616.         TEST    SW1,ASCII       ;don't translate ASCII, of course
  617.         JZ      ML700
  618. ;
  619. ;   Validate ASCII character
  620.         MOV     DL,AL           ;check ASCII for obvious errors
  621.         CMP     DL,1FH
  622.         JA      ML500
  623.         CMP     DL,CR           ;DL is less than 20H, which might be bad
  624.         JE      ML500
  625.         CMP     DL,LF
  626.         JE      ML500
  627.         TEST    SW1,AERRON      ;was last character in error too?
  628.         JZ      ML400
  629.         JMP     READ_ADAPTER
  630. ML400:  MOV     DL,ERR          ;substitute error code
  631.         OR      SW1,AERRON
  632.         JMP     MM700
  633. ML500:  AND     SW1,0FFH-AERRON
  634.         JMP     MM500
  635. ;
  636. ; Translate MURRAY code to ASCII
  637. ML700:  SUB     AH,AH           ;AL contains Murray character
  638.         AND     AL,00011111B    ;Make sure high 3 bits are off
  639.         MOV     BX,AX           ;  and use as base register
  640.         CMP     AL,1BH          ;FIGS character?
  641.         JNE     MM100
  642.         OR      SW1,SHON        ;Set status to FIGS
  643.         JMP     READ_ADAPTER    ;Go read another character
  644. ;
  645. MM100:  CMP     AL,1FH          ;LTRS character?
  646.         JNE     MM200
  647.         AND     SW1,0FFH-SHON   ;Set status to LTRS
  648.         JMP     READ_ADAPTER    ;Go read another character
  649. ;
  650. MM200:  TEST    SW1,SHON        ;Is it FIGS?
  651.         JZ      MM400
  652. ;                                Translate FIGS character
  653.         MOV     DL,FIGTAB╒BXσ
  654.         JMP     MM500
  655. ;                                Translate LTRS character
  656. MM400:  MOV     DL,LTRTAB╒BXσ
  657. ;
  658. MM500:  CMP     DL,0            ;BLANK char?
  659.         JNE     MM700
  660.         JMP     READ_ADAPTER    ;BLANK=no print or carriage movement
  661. ;
  662. MM700:  CALL    DISPLAY_CHAR
  663.         JMP     READ_KEYBD
  664. ;
  665.         SUBTTL  Restore Communications Environment
  666. END_RUN:
  667. ;
  668. ;  Disable Interrupt Enable Register flag
  669.         CALL    DISINT
  670. ;
  671. ;  Disable IRQ4 interrupt on 8259 interrupt controller
  672.         IN      AL,21H          ;Read IMR
  673.         OR      AL,00010000B    ;turn on IRQ4 bit to disable interrupt
  674.         OUT     21H,AL          ;Write OCW1 (IMR)
  675. ;
  676. ;  Clear 0C interrupt handling routine vector.
  677.         PUSH    DS
  678.         MOV     AH,25H          ;Set Interrupt Vector DOS function
  679.         MOV     AL,0CH          ;Interrupt type
  680.         XOR     DX,DX           ;clear address
  681.         MOV     DS,DX
  682.         INT     21H             ;call DOS
  683.         POP     DS
  684. ;
  685. ;  Write Modem Control Register to clear flags
  686.         MOV     DX,COMADDR      ;Load adapter address
  687.         ADD     DX,4            ;Address modem control register (3FC)
  688.         MOV     AL,0            ;All flags clear
  689.         OUT     DX,AL           ;Write MCR register
  690. ;
  691.         CALL    CLEAR           ;Clear the screen
  692.         MOV     AH,2            ;Set cursor position BIOS function
  693.         XOR     DX,DX           ;Row,col = 1,1
  694.         XOR     BH,BH           ;Page 0
  695.         INT     10H             ;Call BIOS
  696. ;
  697. PGMEXIT: RET                    ;Return to DOS
  698. TTY     ENDP
  699. ;
  700. ;  Display character in DL routine
  701. ;
  702. DISPLAY_CHAR PROC NEAR
  703.         PUSH    AX
  704.         PUSH    BX
  705.         PUSH    CX
  706.         CMP     DL,CR
  707.         JNE     SA200
  708.         OR      SW2,CRON        ;Process carrier return
  709.         LOCATE
  710. ; DH = Row, DL = column of cursor position
  711.         XOR     DL,DL           ;Column = 1
  712.         SETCRS                  ;Set cursor position
  713.         JMP     SA900
  714. ;
  715. SA200:  CMP     DL,LF
  716.         JNE     SA400
  717.         OR      SW2,LFON        ;Process line feed
  718.         LOCATE
  719. ; DH = Row, DL = column of cursor position
  720.         INC     DH              ;Next row
  721.         CMP     DH,21           ;Past row 22?
  722.         JNA     SA300
  723. ;
  724.         PUSH    DX
  725.         MOV     AL,1            ;Scroll 1 line
  726.         SCROLL
  727.         POP     DX
  728.         MOV     DH,21           ;Row = 22
  729. ;
  730. SA300:  SETCRS                  ;Set cursor position
  731.         JMP     SA900
  732. ;
  733. SA400:  TEST    SW2,CRON        ;Process the character
  734.         JZ      SA600
  735.         TEST    SW2,LFON        ;If preceding CR not accompanied by
  736.         JNZ     SA600           ;  LF, corrective action is necessary
  737. ;
  738.         LOCATE
  739. ; DH = Row, DL = column of cursor position
  740.         INC     DH              ;Next row
  741.         CMP     DH,21           ;Past row 22?
  742.         JNA     SA500
  743. ;
  744.         PUSH    DX
  745.         MOV     AL,1            ;Scroll 1 line
  746.         SCROLL
  747.         POP     DX
  748.         MOV     DH,21           ;Row = 22
  749. ;
  750. SA500:  SETCRS                  ;Set cursor position
  751. ;
  752. SA600:  MOV     AH,9            ;Write char BIOS function
  753.         XOR     BH,BH           ;Page = 0
  754.         MOV     CX,1            ;Number of characters
  755.         MOV     AL,DL           ;Character
  756.         MOV     BL,00000111B    ;Attribute byte
  757.         INT     10H             ;Call BIOS
  758.         AND     SW2,0FFH-CRON-LFON
  759. ;
  760.         LOCATE                  ;Read cursor position
  761. ; DH = Row, DL = column of cursor position
  762.         INC     DL              ;Next column
  763.         CMP     DL,79           ;Past end of row?
  764.         JNA     SA700
  765. ;
  766.         XOR     DL,DL           ;Reset to column 1
  767.         INC     DH              ;Next row
  768.         CMP     DH,21           ;Past row 22?
  769.         JNA     SA700
  770. ;
  771.         MOV     AL,1            ;Scroll 1 line
  772.         SCROLL
  773.         MOV     DH,21           ;Set cursor to row 22
  774.         MOV     DL,0            ;Set cursor to column 1
  775. ;
  776. SA700:  SETCRS                  ;Set cursor position
  777. ;
  778. SA900:  POP     CX
  779.         POP     BX
  780.         POP     AX
  781.         RET
  782. DISPLAY_CHAR ENDP
  783. ;
  784. ;  Display a Message routine
  785. ;
  786. DISPLAY_MESSAGE PROC NEAR
  787.         PUSH    AX
  788.         PUSH    BX
  789.         PUSH    CX
  790.         PUSH    DX
  791.         LOCATE                  ;Read cursor position
  792. ; DH = Row, DL = column of cursor position
  793.         ADD     DH,2            ;Add 2 giving target row
  794.         CMP     DH,21           ;Compare with line 22
  795.         JA      SC100
  796.         JB      SC300           ;No scroll required
  797.         MOV     AL,1            ;Scroll 1 line only
  798.         JMP     SC200
  799. ;
  800. SC100:  MOV     AL,2            ;Scroll 2 lines
  801. ;
  802. SC200:  SCROLL                  ;Scroll up AL lines
  803. ;
  804.         MOV     DH,21           ;Set cursor to row 22
  805. ;
  806. SC300:  MOV     DL,0            ;Set cursor to column 1
  807.         SETCRS                  ;Set cursor position
  808. ;
  809.         POP     DX              ;Restore message offset
  810.         MOV     AH,9            ;Print String DOS function
  811.         INT     21H             ;Call DOS
  812. ;
  813.         LOCATE                  ;Read cursor position
  814. ;
  815.         ADD     DH,2            ;Add 2 giving target row
  816.         CMP     DH,21           ;Compare with line 22
  817.         JA      SC400
  818.         JB      SC600           ;No scroll required
  819.         MOV     AL,1            ;Scroll 1 line only
  820.         JMP     SC500
  821. ;
  822. SC400:  MOV     AL,2            ;Scroll 2 lines
  823. ;
  824. SC500:  SCROLL                  ;Scroll up AL lines
  825.         MOV     DH,21           ;set cursor to row 22
  826. ;
  827. SC600:  MOV     DL,0            ;column = 1
  828.         SETCRS                  ;set cursor position
  829. ;
  830. SC900:  POP     CX
  831.         POP     BX
  832.         POP     AX
  833.         RET
  834. DISPLAY_MESSAGE ENDP
  835. ;
  836. ;  Send CWID Routine
  837. ;
  838. CWID_RTN PROC  NEAR
  839.         PUSH    BX
  840.         PUSH    CX
  841.         PUSH    DX
  842.         PUSH    SI
  843.         CLD
  844. ;
  845.         MOV     DX,COMADDR      ;Point to 8250 Line Control register
  846.         ADD     DX,3
  847.         MOV     LCRAD,DX        ;Save LCR address
  848.         IN      AL,DX           ;Read current setting of LCR
  849.         TEST    AL,01000000B    ;Is set break bit on?
  850.         JZ      SF100
  851.         AND     AL,10111111B    ;If break bit is on, turn it off
  852.         OUT     DX,AL           ;   and send it back to the adapter
  853. ;
  854. SF100:  MOV     AL,10
  855.         CALL    CWID_PAUSE      ;Pause before sending ID
  856.         MOV     AX,OFFSET CWID
  857.         MOV     CWIDPTR,AX
  858. ;
  859. SF200:  MOV     SI,CWIDPTR
  860.         MOV     AL,BYTE PTR ╒SIσ
  861.         CMP     AL,'$'          ;End of message?
  862.         JNE     SF300
  863.         JMP     SG800           ;All done
  864. ;
  865. SF300:  CMP     AL,' '          ;Space?
  866.         JNE     SF500
  867. ;
  868. SF400:  MOV     AL,2
  869.         CALL    CWID_PAUSE      ;Pause between words
  870.         JMP     SG500
  871. ;
  872. SF500:  MOV     BX,OFFSET TABLE
  873. ;                                Search for character in table
  874. SF600:  MOV     AH,BYTE PTR ╒BXσ
  875.         CMP     AH,0FFH         ;End of the table?
  876.         JNE     SG100
  877.         JMP     SF400           ;Letter not found in table
  878. ;
  879. SG100:  CMP     AL,AH           ;Is this the entry we want?
  880.         JE      SG200
  881.         ADD     BX,7            ;Try next entry in table
  882.         JMP     SF600
  883. ;
  884. SG200:  INC     BX
  885.         MOV     AL,BYTE PTR ╒BXσ
  886.         MOV     AH,AL
  887.         MOV     CL,4
  888.         SHR     AH,CL           ;Extract high-order digit
  889.         AND     AL,0FH          ;Extract low-order digit
  890. ;
  891.         MOV     CX,AX
  892.         MOV     DX,LCRAD
  893.         IN      AL,DX           ;Read current setting of LCR
  894.         OR      AL,01000000B    ;Turn the break bit on
  895.         OUT     DX,AL           ;Send new LCR register contents
  896.         MOV     AL,CH           ;Table byte (value = 1, 2 or 3)
  897.         CALL    CWID_PAUSE
  898. ;
  899.         IN      AL,DX           ;Read current setting of LCR
  900.         AND     AL,10111111B    ;Turn the break bit off
  901.         OUT     DX,AL           ;Send new LCR register contents
  902.         MOV     AL,CL           ;Table byte (value = 1, 2 or 3)
  903.         CALL    CWID_PAUSE
  904. ;
  905.         CMP     CL,2            ;2 = character complete
  906.         JE      SG500
  907.         JMP     SG200           ;Process next segment of character
  908. ;
  909. SG500:  INC     CWIDPTR         ;On to next character
  910.         JMP     SF200
  911. ;
  912. SG800:  POP     SI
  913.         POP     DX
  914.         POP     CX
  915.         POP     BX
  916.         RET
  917. CWID_RTN ENDP
  918. ;
  919. CWID_PAUSE PROC NEAR            ;relative delay in AL (1-8)
  920.         PUSH    CX
  921.         CMP     AL,2            ;2 means end-of-character
  922.         JNE     SJ100
  923.         MOV     AL,3            ;Wait 3 after character complete too
  924. ;
  925. SJ100:  MOV     CX,SPEED
  926. SJ200:  LOOP    SJ200           ;Wait awhile
  927.         DEC     AL
  928.         OR      AL,AL           ;Test for zero
  929.         JNZ     SJ100
  930.         POP     CX
  931.         RET
  932. CWID_PAUSE ENDP
  933. ;
  934.         SUBTTL  Enable interrupt on 8250 communications adapter
  935. ;
  936. ENAINT  PROC    NEAR
  937. ;
  938. ;  Write Interrupt Enable Register to enable 8250 interrupt.
  939.         MOV     DX,COMADDR      ;Reload adapter address
  940.         INC     DX              ;Address Interrupt Enable Reg. (3F9)
  941.         MOV     AL,1            ;Enable Data Available Interrupt
  942.         OUT     DX,AL           ;Send Interrupt Enable Register Data
  943. ;
  944. ;  Update Modem Control Register to enable interrupts
  945.         ADD     DX,3            ;Address modem control register (3FC)
  946.         IN      AL,DX           ;Present MCR contents
  947.         OR      AL,00001000B    ;Turn ON OUT2 flag
  948.         OUT     DX,AL           ;rewrite MCR register
  949. ;
  950. ;  If an interrupt is pending, the 8250 does not honor the enable
  951. ;  until it is cleared.
  952.         SUB     DX,2            ;Interrupt ID. Reg. (3FA)
  953.         IN      AL,DX           ;read Interrupt ID port
  954.         TEST    AL,00000001B    ;0 if interrupt pending
  955.         JNZ     SM900
  956.         SUB     DX,2            ;Receiver Buffer Reg. (3F8)
  957.         IN      AL,DX           ;clear pending interrupt - discard byte
  958. SM900:  RET
  959. ENAINT  ENDP
  960. ;
  961.         SUBTTL  Disable interrupts on 8250 communications adapter
  962. ;
  963. DISINT  PROC    NEAR
  964. ;
  965. ;  Write Interrupt Enable Register to disable 8250 interrupt.
  966.         MOV     DX,COMADDR      ;Reload adapter address
  967.         INC     DX              ;Point to Interrupt Enable Register (3F9
  968.         MOV     AL,0            ;Disable all interrupts
  969.         OUT     DX,AL           ;Send Interrupt Enable Register Data
  970. ;
  971. ;  Update Modem Control Register to disable interrupts
  972.         ADD     DX,3            ;Point to modem control register (3FC)
  973.         IN      AL,DX           ;Present MCR contents
  974.         AND     AL,11110111B    ;Turn OUT2 OFF
  975.         OUT     DX,AL           ;Rewrite MCR register
  976.         RET
  977. DISINT  ENDP
  978. ;
  979.         SUBTTL  Turn ON/OFF Request to Send signal
  980. ;
  981. RTSON   PROC    NEAR
  982. ;
  983. ; Update Modem Control Register to turn on RTS flag
  984.         MOV     DX,COMADDR      ;Comm Adapter Address
  985.         ADD     DX,4            ;point to modem control register (3FC)
  986.         IN      AL,DX           ;get current contents of register
  987.         OR      AL,00000010B    ;Turn bit 1 ON  (RTS line)
  988.         OUT     DX,AL           ;rewrite MCR register
  989.         RET
  990. RTSON   ENDP
  991. ;
  992. RTSOFF  PROC    NEAR
  993. ;
  994. ; Update Modem Control Register to turn off RTS flag
  995.         MOV     DX,COMADDR      ;Comm Adapter Address
  996.         ADD     DX,4            ;point to modem control register (3FC)
  997.         IN      AL,DX           ;get current contents of register
  998.         AND     AL,11111101B    ;Turn bit 1 OFF (RTS line)
  999.         OUT     DX,AL           ;Rewrite MCR register
  1000.         RET
  1001. RTSOFF  ENDP
  1002. ;
  1003. ;  Send character in AL
  1004. XMIT_CHAR PROC  NEAR
  1005.         PUSH    DX
  1006.         PUSH    AX              ;Save input character
  1007. ;
  1008. XM200:  MOV     DX,COMADDR      ;Load adapter address
  1009.         ADD     DX,5            ;Adress of Line Status Reg. (3FD)
  1010.         IN      AL,DX           ;Read LSR
  1011.         TEST    AL,00100000B    ;Test TX hold register empty?
  1012.         JNZ     XM400           ;Ready to accept data
  1013.         JMP     XM200           ;Not ready so try again
  1014. ;
  1015. XM400:  MOV     DX,COMADDR      ;Load adapter address THR (3F8)
  1016.         POP     AX              ;Restore character
  1017.         OUT     DX,AL           ;Write to THR
  1018.         POP     DX
  1019.         RET
  1020. XMIT_CHAR ENDP
  1021. ;
  1022. PAUSE   PROC    NEAR            ;PAUSE routine
  1023.         PUSH    CX
  1024.         XOR     CX,CX
  1025. SP100:  LOOP    SP100
  1026.         POP     CX
  1027.         RET
  1028. PAUSE   ENDP
  1029. ;
  1030. CLEAR   PROC    NEAR            ;CLEAR SCREEN Routine
  1031.         MOV     AH,6            ;Scroll up BIOS function
  1032.         MOV     AL,0            ;Clear screen request
  1033.         XOR     CX,CX           ;Start row,col = 1,1
  1034.         MOV     DH,24           ;End row = 25
  1035.         MOV     DL,79           ;End col = 80
  1036.         MOV     BH,00000111B    ;Attribute byte
  1037.         INT     10H             ;Call BIOS
  1038. ;
  1039.         RET
  1040. CLEAR   ENDP
  1041. ;
  1042.         SUBTTL  ALARM - Sound the ALARM
  1043. ;
  1044. TIMER   EQU     40H
  1045. PORT_B  EQU     61H             ;8255 port B addr
  1046. ;
  1047. ALARM   PROC    NEAR
  1048.         PUSH    CX
  1049.         CLD
  1050.         MOV     AL,10110110B    ;SEL TIM 2, LSB,MSB,Binary
  1051.         OUT     TIMER+3,AL      ;Write the Timer Mode Reg
  1052.         MOV     AX,400H
  1053.         OUT     TIMER+2,AL      ;Write Timer 2 cnt - LSB
  1054.         MOV     AL,AH
  1055.         OUT     TIMER+2,AL      ;Write Timer 2 cnt - MSB
  1056.         IN      AL,PORT_B       ;Get current setting of port
  1057.         MOV     AH,AL           ;Save the setting
  1058.         OR      AL,03           ;Turn speaker on
  1059.         OUT     PORT_B,AL
  1060.         SUB     CL,CL           ;Set cnt to wait awhile
  1061.         MOV     CH,64
  1062. ST100:  LOOP    ST100           ;Delay before turning off
  1063.         MOV     AL,AH           ;Recover value of port
  1064.         OUT     PORT_B,AL
  1065.         POP     CX
  1066.         RET
  1067. ALARM   ENDP
  1068. ;
  1069.         SUBTTL  TTYINTR - Adapter Interrupt 0C Routine
  1070. ;
  1071. INT0C   PROC    FAR
  1072.         STI                     ;Enable interrupts
  1073.         PUSH    AX
  1074.         PUSH    BX
  1075.         PUSH    CX
  1076.         PUSH    DX
  1077.         PUSH    SI
  1078.         PUSH    DI
  1079.         CLD
  1080. ;
  1081. SW100:  MOV     DX,COMADDR      ;Load adapter address
  1082.         ADD     DX,5            ;Address the Line Status Register (3FD)
  1083.         IN      AL,DX           ;Read Line Status Register
  1084.         TEST    AL,01H          ;Test Data Ready bit
  1085.         JNZ     SW300           ;One means data is available in receive
  1086.         JMP     SW900           ;No data, so quit
  1087. ;
  1088. ; The following statuses (of interest) are possible in AL:
  1089. ; Bit 3 = FRAMING ERROR         Bit 1 = OVERRUN ERROR
  1090. SW300:  MOV     CL,AL           ;Save status byte in CL
  1091.         MOV     DX,COMADDR      ;Get Receive Buffer Register addr (3F8)
  1092.         IN      AL,DX           ;Read one byte from adapter
  1093.         MOV     CH,AL           ;Save data byte in CH
  1094. ;
  1095.         SUB     BH,BH
  1096.         MOV     BL,INPTR
  1097.         MOV     ADBUF╒BXσ,CH    ;Store data byte in buffer
  1098.         MOV     ERBUF╒BXσ,CL    ;Store status byte in buffer
  1099. ;
  1100.         INC     BL              ;Point to next byte in buffers
  1101.         CMP     BL,ADLEN        ;Check for wrap-around in buffer
  1102.         JB      SW500
  1103.         SUB     BL,BL           ;Reset pointer at wrap-around
  1104. SW500:  MOV     INPTR,BL        ;Update pointer
  1105.         MOV     CL,ADCNT
  1106.         INC     CL              ;Increment active byte count
  1107.         CMP     CL,ADLEN        ;Check for buffer overrun
  1108.         JNA     SW700
  1109.         MOV     CL,1            ;Throw away buffer contents when overrun
  1110. SW700:  MOV     ADCNT,CL
  1111. ;
  1112. SW900:  CLI                     ;Disable interrupts
  1113.         MOV     AL,20H          ;Signal end of interrupt to
  1114.         OUT     20H,AL          ;  8259 via OCW2 register
  1115.         POP     DI
  1116.         POP     SI
  1117.         POP     DX
  1118.         POP     CX
  1119.         POP     BX
  1120.         POP     AX
  1121.         IRET
  1122. INT0C   ENDP
  1123. ;
  1124. CODE    ENDS
  1125.         END     TTY
  1126.